home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
linux.68k
/
docs
/
dd-dri~1.z
/
dd-dri~1
Wrap
Text File
|
1993-04-12
|
33KB
|
948 lines
************************************************************
* *
* Guide To Linux Driver Writing -- Character Devices *
* *
* or, *
* *
* The Wacky World of Driver Development (I) *
* *
* Last Revision: Apr 11, 1993 *
* *
************************************************************
This document (C) 1993 Robert Baruch. This document may be freely
copied as long as the entire title, copyright, this notice, and all of
the introduction are included along with it. Suggestions, criticisms,
and comments to baruch@nynexst.com. This document, nor the work
performed by Robert Baruch using Linux, nor the results of said work
are connected in any way to any of the Nynex companies. Information
may settle during transportation. This product should not be used
in conjunction with a dietary regime except under supervision by your
doctor.
Right, now that that's over with, let's get into the fun stuff!
========================
Introduction
========================
There is a companion guide to this Guide, the Linux Character Device
Tutorial. This tutorial contains working examples of driver code. It
introduces the reader gently into each aspect of character device driver
writing through experiments which are carried out by the programmer.
This Guide should serve as a reference to both beginning and advanced
driver writers.
-=-=-=-=-=-=-
Some words of thanks:
Many thanks to:
Donald J. Becker (becker@metropolis.super.org)
Don Holzworth (donh@gcx1.ssd.csd.harris.com)
Michael Johnson (johnsonm@stolaf.edu)
Karl Heinz Kremer (khk@raster.kodak.com)
All the driver writers!
...and of course, Linus "Linux" Torvalds and all the guys who helped
develop Linux into a BLOODY KICKIN' O/S!
-=-=-=-=-=-=-
...and now a word of warning:
Messing about with drivers is messing with the kernel. Drivers are run
at the kernel level, and as such are not subject to scheduling. Further,
drivers have access to various kernel structures. Before you actually
write a driver, be *damned* sure of what you are doing, lest you end
up having to re-format your harddrive and re-install Linux!
The information in this Guide is as up-to-date as I could make it. It also
has no stamp of approval whatsoever by any of the designers of the kernel.
I am not responsible for damage caused to anything as a result of using this
Guide.
========================
End of Introduction
========================
Kernal-callable functions:
--------------------------
Note: There is no close for a character device. There is only release.
See the file data structure below to find out how to determine the number
of processes which have the device open.
-=-=-=-=-=-=-=-
init : Initializes the driver on bootup.
unsigned long driver_init(unsigned long kmem_start, unsigned long kmem_end)
Arguments: kmem_start -- the start of kernel memory
kmem_end -- the end of kernel memory
Returns: The new start of kernel memory. This will be different from the
kmem_start argument if you want to allocate memory for the driver.
The arguments you use depends on what you want to do. Remember that since
you are going to add your init function to kernel/chr_dev/mem.c, you can
make your call anything you like, but you have access to the kernel memory
start and end.
Generally, the init function initializes the driver and hardware, and
displays some message telling of the availability of the driver and
hardware. In addition, the register_chrdev function is usually called here.
**************
open : Open a device
static int driver_open(struct inode * inode, struct file * file)
Arguments: inode -- pointer to the inode structure for this device
file -- pointer to the file structure for this device
Returns: 0 on success,
-errno on error.
This function is called whenever a process performs open (or fopen) on
the device special file. If there is no open function for the driver,
nothing spectacular happens. As long as the /dev file exists, the
open will succeed.
**************
read : Read from a device
static int driver_read(struct inode * inode, struct file * file,
char * buffer, int count)
Arguments: inode -- pointer to the inode structure for this device
file -- pointer to the file structure for this device
buffer -- pointer to the buffer in user space to read into
count -- the number of bytes to read
Returns: -errno on error
>=0 : the number of bytes actually read
If there is no read function for the driver, read calls will return EINVAL.
**************
write : Write to a device
static int driver_write(struct inode * inode, struct file * file,
char * buffer, int count)
Arguments: inode -- pointer to the inode structure for this device
file -- pointer to the file structure for this device
buffer -- pointer to the buffer in user space to write from
count -- the number of bytes to write
Returns: -errno on error
>=0 : the number of bytes actually written
If there is no write function for the driver, write calls will return
EINVAL.
**************
lseek : Change the position offset of the device
static int driver_lseek(struct inode * inode, struct file * file,
off_t offset, int origin)
Arguments: inode -- pointer to the inode structure for this device
file -- pointer to the file structure for this device
offset -- offset from origin to move to (bytes)
origin -- origin to move from :
0 = from origin 0 (beginning)
1 = from current position
2 = from end
Returns: -errno on error
>=0 : the position after the move
See Also: Data Structure 'file'
If there is no lseek function for the driver, the kernel will take the default
seek action, which is to alter the file->f_pos element. For origins of 2,
the default action results in -EINVAL if file->f_inode is NULL, or it
sets file->f_pos to file->f_inode->i_size + offset otherwise.
**************
ioctl : Various device-dependent services
static int driver_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
Arguments: inode -- pointer to the inode structure for this device
file -- pointer to the file structure for this device
cmd -- the user-defined command to perform
arg -- the user-defined argument. You may use this
as a pointer to user space, since sizeof(long)==
sizeof(void *).
Returns: -errno on error
>=0 : whatever you like! (user-defined)
For cmd, FIOCLEX, FIONCLEX, FIONBIO, and FIOASYNC are already defined.
See the file linux/fs/ioctl.c, sys_ioctl to find out what they do.
If there is no ioctl call for the driver, and the ioctl command performed
is not one of the four types listed here, ioctl will return -EINVAL.
**************
select : Performs the select call on the device:
static int driver_select(struct inode *inode, struct file *file,
int sel_type, select_table * wait)
Arguments: inode -- pointer to the inode structure for this device
file -- pointer to the file structure for this device
sel_type -- the select type to perform :
SEL_IN (read)
SEL_OUT (write)
SEL_EX (exception)
wait -- see the section "Some Notes" for select.
Returns: 0 if the device is not ready to perform the sel_type operation
!=0 if it is.
See the "Some Notes" section 'way below on information on h